package com.cpoopc.fuckapp.utils.security;


import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.util.Log;

/**
 * 提供AES加密支持
 * <p>
 * Description:描述
 * </p>
 */
public class AES {

	private static final String TAG = "AES";

	/**
	 * 对输入进行AES加密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param byteinfo
	 *            被加密内容，如果为null则返回null
	 * @return 加密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] encrypt(byte[] key, byte[] byteinfo) throws SecurityException {
		if (null == key || key.equals("")) {
			throw new IllegalArgumentException(SecurityUtil.ERROR_KEY_IS_NULL);
		}
		if (null == byteinfo || byteinfo.equals("")) {
			return null;
		}
		SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
		Cipher cipher;
		try {
			cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			return cipher.doFinal(byteinfo);
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		} catch (NoSuchPaddingException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchPaddingException");
		} catch (InvalidKeyException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("InvalidKeyException");
		} catch (IllegalBlockSizeException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("IllegalBlockSizeException");
		} catch (BadPaddingException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("BadPaddingException");
		}
	}

	/**
	 * 对输入进行AES加密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param info
	 *            被加密内容，如果为null则返回null
	 * @return 加密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] encrypt(String key, String info) throws SecurityException {
		byte[] rawKey;
		try {
			rawKey = getRawKey(key.getBytes());
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		}
		return encrypt(rawKey, info.getBytes());
	}

	/**
	 * 对输入进行AES加密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param byteinfo
	 *            被加密内容，如果为null则返回null
	 * @return 加密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] encrypt(String key, byte[] byteinfo) throws SecurityException {
		byte[] rawKey;
		try {
			rawKey = getRawKey(key.getBytes());
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		}
		return encrypt(rawKey, byteinfo);
	}

	/**
	 * 对输入进行AES加密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param info
	 *            被加密内容，如果为null则返回null
	 * @return 加密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] encrypt(byte[] key, String info) throws SecurityException {
		return encrypt(key, info.getBytes());
	}

	/**
	 * 对输入进行AES解密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param byteinfo
	 *            被解密内容，如果为null则返回null
	 * @return 解密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] decrypt(byte[] key, byte[] byteinfo) throws SecurityException {
		if (null == key || key.equals("")) {
			throw new IllegalArgumentException(SecurityUtil.ERROR_KEY_IS_NULL);
		}
		if (null == byteinfo || byteinfo.equals("")) {
			return null;
		}
		try {
			SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec);
			return cipher.doFinal(byteinfo);
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		} catch (NoSuchPaddingException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchPaddingException");
		} catch (InvalidKeyException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("InvalidKeyException");
		} catch (IllegalBlockSizeException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("IllegalBlockSizeException");
		} catch (BadPaddingException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("BadPaddingException");
		}
	}

	/**
	 * 
	 * 对输入进行AES解密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param info
	 *            被解密内容，如果为null则返回null
	 * @return 解密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] decrypt(String key, InputStream info) throws SecurityException {
		byte[] rawKey;
		byte[] byteinfo;
		try {
			byteinfo = SecurityUtil.getByteFromInputStream(info);
		} catch (IOException e1) {
			e1.printStackTrace();
			throw new SecurityException("IOException");
		}
		try {
			rawKey = getRawKey(key.getBytes());
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		}
		return decrypt(rawKey, byteinfo);
	}

	/**
	 * 对输入进行AES解密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param byteinfo
	 *            被解密内容，如果为null则返回null
	 * @return 解密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] decrypt(String key, byte[] byteinfo) throws SecurityException {
		byte[] rawKey;
		try {
			rawKey = getRawKey(key.getBytes());
		} catch (NoSuchAlgorithmException e) {
			Log.w(TAG, "" + e.getMessage());
			throw new SecurityException("NoSuchAlgorithmException");
		}
		return decrypt(rawKey, byteinfo);
	}

	/**
	 * 对输入进行AES解密
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @param info
	 *            被解密内容，如果为null则返回null
	 * @return 解密后内容，如果为null说明输入为null
	 * @throws SecurityException
	 *             加密失败时抛出异常,具体异常通过getMessage查看
	 */
	public static byte[] decrypt(byte[] key, InputStream info) throws SecurityException {
		byte[] byteinfo;
		try {
			byteinfo = SecurityUtil.getByteFromInputStream(info);
		} catch (IOException e1) {
			e1.printStackTrace();
			throw new SecurityException("IOException");
		}
		return decrypt(key, byteinfo);
	}

	/**
	 * 生成AES加密所需秘钥
	 * 
	 * @param key
	 *            用于生成秘钥
	 * @return
	 * @throws NoSuchAlgorithmException
	 *             采用AES加密算法时不会发生此问题
	 */
	private static byte[] getRawKey(byte[] key) throws NoSuchAlgorithmException {
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
		sr.setSeed(key);
		kgen.init(128, sr); // 192 and 256 bits may not be available
		SecretKey skey = kgen.generateKey();
		byte[] raw = skey.getEncoded();
		return raw;
	}
}
